`default_nettype none

module debounce_m #(
    parameter [31:0] MAX_COUNT_CP_I   = 30,
    parameter [ 0:0] INIT_STATUS_CP_I = 0
) (
    input rst_w_ni,
    input clk_w_i,
    input signal_w_i,

    output stat_w_o
);
    localparam [31:0] WIDTH_CP_L = $clog2(MAX_COUNT_CP_I);
    localparam [WIDTH_CP_L-1:0] INIT_COUNT_CP_L =
        MAX_COUNT_CP_I * INIT_STATUS_CP_I;
    localparam [WIDTH_CP_L:0] INIT_REG_VALUE_CP_L =
        (INIT_COUNT_CP_L << 1) | INIT_STATUS_CP_I;

    wire [WIDTH_CP_L-1:0] get_counter_wp_l;
    wire get_stat_w_l;

    wire [WIDTH_CP_L-1:0] set_counter_if_1_wp_l;
    wire set_stat_if_1_w_l;
    assign {set_counter_if_1_wp_l, set_stat_if_1_w_l} =
        (get_counter_wp_l < MAX_COUNT_CP_I) ?
        {get_counter_wp_l + 1, get_stat_w_l} :
        {{WIDTH_CP_L{MAX_COUNT_CP_I}}, 1'b1};

    wire [WIDTH_CP_L-1:0] set_counter_if_0_wp_l;
    wire set_stat_if_0_w_l;
    assign {set_counter_if_0_wp_l, set_stat_if_0_w_l} = (get_counter_wp_l > 0) ?
        {get_counter_wp_l - 1, get_stat_w_l} : {{WIDTH_CP_L{0}}, 1'b0};

    wire [WIDTH_CP_L-1:0] set_counter_wp_l;
    wire set_stat_w_l;
    assign {set_counter_wp_l, set_stat_w_l} = (signal_w_i == 0) ?
        {set_counter_if_0_wp_l, set_stat_if_0_w_l} :
        {set_counter_if_1_wp_l, set_stat_if_1_w_l};

    dreg_m #(
        .WIDTH_CP_I(WIDTH_CP_L + 1),
        .INIT_VALUE_CP_I(INIT_REG_VALUE_CP_L)
    ) counter_i_l (
        .rst_w_ni(rst_w_ni),
        .clk_w_i(clk_w_i),
        .set_en_w_pi(1),
        .set_wp_i({set_counter_wp_l, set_stat_w_l}),

        .get_wp_o({get_counter_wp_l, get_stat_w_l})
    );

    assign stat_w_o = get_stat_w_l;
endmodule
